package com.t2t.top.framework.diamond;

import com.taobao.diamond.manager.ManagerListener;
import com.taobao.diamond.manager.impl.DefaultDiamondManager;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Diamond环境配置管理.
 *
 * @author yangpengfei
 */
public class DiamondEnv extends Env {

    static Logger logger = LoggerFactory.getLogger(DiamondEnv.class);

    private static final ConcurrentMap<String, PropertyBo> diamondProperty = new ConcurrentHashMap<>();

    private static final ConcurrentMap<String, String> env = new ConcurrentHashMap<>();

    private static final String REGEX_BIND = "bind\\((.*?)\\)";

    /**
     * 初始化环境
     */
    public static void initEnv() {
        PropertiesLoader propertiesLoader = new PropertiesLoader();
        Properties properties = propertiesLoader.mergeProperties();

        List<PropertyBo> propertyBos = new ArrayList<>();
        for (Object k : properties.keySet()) {
            String key = k.toString();
            String value = properties.getProperty(key);
            if (value.contains("bind")) {
                PropertyBo bo = buildPropertyBo(key, value);
                propertyBos.add(bo);
            } else {
                env.put(key, value);
            }
        }

        Set<String> set = new HashSet<>();
        for (PropertyBo bo : propertyBos) {
            set.add(bo.getDataId());
        }

        Map<String, String> result = buildContentByDataIds(set);
        Map<String, Properties> resultCacheExt = new HashMap();

        for (PropertyBo bo : propertyBos) {
            String content = result.get(bo.getDataId());
            if (Properties.class.isAssignableFrom(bo.getTypeOfContent())) {
                Properties pv = resultCacheExt.get(bo.getDataId());
                if (pv == null) {
                    pv = PropertiesUtils.toProperties(content);
                    resultCacheExt.put(bo.getDataId(), pv);
                }
                String value = pv.getProperty(bo.getKey());
                bo.setValue(StringUtils.defaultIfBlank(value, bo.getDefaultValue()));
                env.put(bo.getKey(), bo.getValue());
            }

            if (String.class.isAssignableFrom(bo.getTypeOfContent())) {
                bo.setValue(StringUtils.defaultIfBlank(content, bo.getDefaultValue()));
                env.put(bo.getKey(), bo.getValue());
            }

            diamondProperty.put(bo.getDataId(), bo);
        }
    }

    public static String getValue(String key) {
        return StringUtils.defaultIfBlank(env.get(key), "");
    }

    public static String getValue(String dataId, String defaultValue) {
        return StringUtils.defaultIfBlank(env.get(dataId), defaultValue);
    }

    public static PropertyBo getDiamondProperty(String dataId) {
        return diamondProperty.get(dataId);
    }

    public static Map<String, String> buildContentByDataIds(Set<String> dataIds) {
        String groupId = getDefaultGroupId();
        int port = getDefalutPort();
        int timeout = getDefalutTimeout();
        List<ManagerListener> managerListenerList = new ArrayList<>();
        Map result = new HashMap();
        for (String dataId : dataIds) {
            DefaultDiamondManager diamondManager = new DefaultDiamondManager(groupId, dataId, managerListenerList);
            diamondManager.getDiamondConfigure().setPort(port);
            String configInfo = diamondManager.getAvailableConfigureInfomation(timeout);
            if (configInfo == null) {
                logger.error("group={} dataId={} 在diamond中找不着!", groupId, dataId);
            }
            result.put(dataId, configInfo);
        }
        return result;
    }


    public static PropertyBo buildPropertyBo(String propertyName, String propertyValue) {
        PropertyBo bo = new PropertyBo();
        String dataId = null;
        Pattern pattern = Pattern.compile(REGEX_BIND);
        Matcher matcher = pattern.matcher(propertyValue);
        while (matcher.find()) {
            dataId = matcher.group(1);
        }

        //是否有参数, 如果有, 则从bind(dataId)中取出dataId，否则取propertyName
        if (dataId == null) {
            bo.setDataId(propertyName);
            bo.setDefaultValue(propertyValue);
            bo.setGroupId(getDefaultGroupId());
            bo.setTypeOfContent(String.class);
        } else {
            bo.setDataId(dataId);
            bo.setKey(propertyName);
            bo.setDefaultValue(propertyValue);
            bo.setGroupId(getDefaultGroupId());
            bo.setTypeOfContent(Properties.class);
        }
        return bo;
    }

    public static ConcurrentMap<String, String> getEnv() {
        return env;
    }
}